/*
 * Copyright (c) 2022, IMMORTA Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * - Neither the name of IMMORTA Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef SPWM_DRV_H
#define SPWM_DRV_H

/*!
 * @file spwm_drv.h
 * @brief This file declares spwm driver interfaces
 */

/*!
 * @addtogroup spwm_drv
 * @{
 */

/*******Includes***************************************************************/
#include "device_registers.h"
#include "errcodes.h"
#include "stdio.h"

#include <stdbool.h>
#include <stdint.h>

/*******Definitions************************************************************/
/*!
 * @brief SPWM interrupt status structure
 */
typedef struct
{
    uint8_t overflowStatus;  /*!< Overflow flag */
    uint8_t underflowStatus; /*!< Underflow flag */
    uint8_t channelStatus;   /*!< Channel status */
    uint8_t faultStatus;     /*!< Fault status */
} spwm_int_state_t;

/*!
 * @brief Callback for all peripherals which support SPWM features
 */
typedef void (*spwm_callback_t)(uint32_t instance, void *param);

/*!
 * @brief SPWM channel enumeration
 */
typedef enum
{
    SPWM_CH_0   = 0U, /*!< PWM channel 0 */
    SPWM_CH_1   = 1U, /*!< PWM channel 1 */
    SPWM_CH_2   = 2U, /*!< PWM channel 2 */
    SPWM_CH_3   = 3U, /*!< PWM channel 3 */
    SPWM_CH_4   = 4U, /*!< PWM channel 4 */
    SPWM_CH_5   = 5U, /*!< PWM channel 5 */
    SPWM_CH_6   = 6U, /*!< PWM channel 6 */
    SPWM_CH_7   = 7U, /*!< PWM channel 7 */
    SPWM_CH_MAX = 8U  /*!< Invalid channel */
} spwm_channel_t;

/*!
 * @brief SPWM dual channel enumeration
 */
typedef enum
{
    SPWM_DUAL_CH_0   = 0U, /*!< PWM dual channel 0 */
    SPWM_DUAL_CH_1   = 1U, /*!< PWM dual channel 1 */
    SPWM_DUAL_CH_2   = 2U, /*!< PWM dual channel 2 */
    SPWM_DUAL_CH_3   = 3U, /*!< PWM dual channel 3 */
    SPWM_DUAL_CH_MAX = 4U  /*!< Invalid dual channel */
} spwm_dual_channel_t;

/*!
 * @brief SPWM counting mode enumeration
 */
typedef enum
{
    SPWM_UP_COUNT      = 0U, /*!< Up counting mode */
    SPWM_UP_DOWN_COUNT = 1U  /*!< Up-down counting mode */
} spwm_count_mode_t;

/*!
 * @brief SPWM deadtime psc enumeration
 */
typedef enum
{
    SPWM_DEADTIME_DIVID_1  = 1U, /*!< Divide by 1 */
    SPWM_DEADTIME_DIVID_4  = 2U, /*!< Divide by 4 */
    SPWM_DEADTIME_DIVID_16 = 3U  /*!< Divide by 16 */
} spwm_deadtime_psc_t;

/*!
 * @brief SPWM channel output active polarity enumeration
 */
typedef enum
{
    SPWM_OUTPUT_POLARITY_ACTIVE_HIGH = 0U, /*!< The channel output polarity is active high */
    SPWM_OUTPUT_POLARITY_ACTIVE_LOW  = 1U  /*!< The channel output polarity is active low */
} spwm_active_output_polarity_t;

/*!
 * @brief SPWM output level enumeration
 */
typedef enum
{
    SPWM_LOW_LEVEL  = 0U, /*!< LOW LEVEL */
    SPWM_HIGH_LEVEL = 1U  /*!< HIGH LEVEL */
} spwm_output_level_t;

/*!
 * @brief SPWM channel match point counting direction in combine mode enumeration
 */
typedef enum
{
    SPWM_MATCH_DIR_DOWN = 0U, /*!< Channel match point in down counting direction */
    SPWM_MATCH_DIR_UP   = 1U  /*!< Channel match point in up counting direction */
} spwm_match_dir_t;

/*!
 * @brief SPWM input sensitive edge enumeration
 */
typedef enum
{
    SPWM_RISING_EDGE_DETECT  = 1U, /*!< Rising edge detect */
    SPWM_FALLING_EDGE_DETECT = 2U, /*!< Falling Edge detect */
    SPWM_BOTH_EDGE_DETECT    = 3U  /*!< Rising or falling edge detect */
} spwm_input_sensitive_edge_t;

/*!
 * @brief SPWM input filter prescaler enumeration
 */
typedef enum
{
    SPWM_INPUT_FILTER_PSC_1    = 0U,  /*!< Input filter prescaler is 1 */
    SPWM_INPUT_FILTER_PSC_2    = 1U,  /*!< Input filter prescaler is 2 */
    SPWM_INPUT_FILTER_PSC_4    = 2U,  /*!< Input filter prescaler is 4 */
    SPWM_INPUT_FILTER_PSC_8    = 3U,  /*!< Input filter prescaler is 8 */
    SPWM_INPUT_FILTER_PSC_16   = 4U,  /*!< Input filter prescaler is 16 */
    SPWM_INPUT_FILTER_PSC_32   = 5U,  /*!< Input filter prescaler is 32 */
    SPWM_INPUT_FILTER_PSC_64   = 6U,  /*!< Input filter prescaler is 64 */
    SPWM_INPUT_FILTER_PSC_128  = 7U,  /*!< Input filter prescaler is 128 */
    SPWM_INPUT_FILTER_PSC_256  = 8U,  /*!< Input filter prescaler is 256 */
    SPWM_INPUT_FILTER_PSC_512  = 9U,  /*!< Input filter prescaler is 512 */
    SPWM_INPUT_FILTER_PSC_1024 = 10U, /*!< Input filter prescaler is 1024 */
    SPWM_INPUT_FILTER_PSC_2048 = 11U, /*!< Input filter prescaler is 2048 */
    SPWM_INPUT_FILTER_PSC_4096 = 12U  /*!< Input filter prescaler is 4096 */
} spwm_input_filter_psc_t;

/*!
 * @brief SPWM event ratio enumeration
 */
typedef enum
{
    SPWM_CH_EVENT_RATIO_1 = 0U, /*!< Channel event ratio is 1 */
    SPWM_CH_EVENT_RATIO_2 = 1U, /*!< Channel event ratio is 2 */
    SPWM_CH_EVENT_RATIO_4 = 2U, /*!< Channel event ratio is 4 */
    SPWM_CH_EVENT_RATIO_8 = 3U  /*!< Channel event ratio is 8 */
} spwm_ch_event_ratio_t;

/*!
 * @brief SPWM dual edge capture mode enumeration
 */
typedef enum
{
    SPWM_POSITIVE_PLUSE_WIDTH_CAPTURE = 0U, /*!< Positive Pluse width capture */
    SPWM_NEGATIVE_PLUSE_WIDTH_CAPTURE = 1U, /*!< Negative Pluse width capture */
    SPWM_RISING_EDGE_PERIOD_CAPTURE   = 2U, /*!< Period capture between two consecutive rising edges */
    SPWM_FALLING_EDGE_PERIOD_CAPTURE  = 3U  /*!< Period capture between two consecutive falling edges */
} spwm_dual_edge_capture_t;

/*!
 * @brief SPWM external trigger ratio enumeration
 */
typedef enum
{
    SPWM_TRIGGER_RATIO_1 = 0U, /*!< Trigger Ratio is 1 */
    SPWM_TRIGGER_RATIO_2 = 1U, /*!< Trigger Ratio is 2 */
    SPWM_TRIGGER_RATIO_3 = 2U, /*!< Trigger Ratio is 3 */
    SPWM_TRIGGER_RATIO_4 = 3U, /*!< Trigger Ratio is 4 */
    SPWM_TRIGGER_RATIO_5 = 4U, /*!< Trigger Ratio is 5 */
    SPWM_TRIGGER_RATIO_6 = 5U, /*!< Trigger Ratio is 6 */
    SPWM_TRIGGER_RATIO_7 = 6U, /*!< Trigger Ratio is 7 */
    SPWM_TRIGGER_RATIO_8 = 7U  /*!< Trigger Ratio is 8 */
} spwm_trigger_ratio_t;

/*!
 * @brief SPWM fault channel input polarity active enumeration
 */
typedef enum
{
    SPWM_INPUT_POLARITY_ACTIVE_HIGH = 0U, /*!< The fault channel polarity is active high */
    SPWM_INPUT_POLARITY_ACTIVE_LOW  = 1U  /*!< The fault channel polarity is active low */
} spwm_fault_input_polarity_active_t;

/*!
 * @brief SPWM sync trigger mode enumeration
 */
typedef enum
{
    SPWM_SYNC_TRIGGER_SOFTWARE = 0U, /*!< Software trigger synchronization */
    SPWM_SYNC_TRIGGER_HARDWARE = 1U  /*!< Hardware trigger synchronization */
} spwm_sync_trigger_mode_t;

/*!
 * @brief SPWM channel fault control mode enumeration
 */
typedef enum
{
    SPWM_FAULT_CTRL_MANUAL = 0U, /*!< Fault control is enabled for manual fault clearing */
    SPWM_FAULT_CTRL_AUTO   = 1U  /*!< Fault control is enabled for automatic fault clearing */
} spwm_fault_ctrl_mode_t;

/*!
 * @brief SPWM output compare mode enumeration
 */
typedef enum
{
    SPWM_NONE_OUTPUT   = 0U, /*!< No output */
    SPWM_TOGGLE_OUTPUT = 1U, /*!< Toggle output */
    SPWM_CLEAR_OUTPUT  = 2U, /*!< Clear output */
    SPWM_SET_OUTPUT    = 3U  /*!< Set output */
} spwm_output_compare_mode_t;

/*!
 * @brief SPWM output mode enumeration
 */
typedef enum
{
    SPWM_OUTPUT_HIGH_TRUE = 0U, /*!< Output is high true */
    SPWM_OUTPUT_LOW_TRUE  = 1U  /*!< Output is low true */
} spwm_output_mode_t;

/*!
 * @brief SPWM fault input enumeration
 */
typedef enum
{
    SPWM_FAULT_INPUT_0 = 0U, /*!< Fault input 0 */
    SPWM_FAULT_INPUT_1 = 1U, /*!< Fault input 1 */
    SPWM_FAULT_INPUT_2 = 2U, /*!< Fault input 2 */
    SPWM_FAULT_INPUT_3 = 3U  /*!< Fault input 3 */
} spwm_fault_input_t;

/*!
 * @brief SPWM counter configuration structure
 */
typedef struct
{
    uint8_t  clkPsc;          /*!< Clock prescaler */
    bool     cntEn;           /*!< Enable/Disable counter */
    uint16_t initValue;       /*!< Initial counter value */
    uint16_t modValue;        /*!< Maximum counter value */
    bool     overflowIntEn;   /*!< Enable/Disable CNTOF interrupt */
    bool     underflowIntEn;  /*!< Enable/Disable CNTUF interrupt */
    uint8_t  cntOverflowFreq; /*!< CNTOF frequency */
} spwm_counter_config_t;

/*!
 * @brief SPWM independent channel configuration structure
 */
typedef struct
{
    spwm_channel_t                channel;        /*!< Independent channel number */
    uint16_t                      chValue;        /*!< Channel match value */
    spwm_output_mode_t            levelMode;      /*!< Output mode */
    spwm_active_output_polarity_t polarity;       /*!< Polarity of the channel output */
    spwm_output_level_t           initLevel;      /*!< Channel init output level */
    bool                          matchTriggerEn; /*!< Enable/Disable channel match trigger */
    spwm_ch_event_ratio_t         eventRatio;     /*!< Event prescaler */
    bool                          chIntEn;        /*!< Enable/Disable channel interrupt */
} spwm_independent_ch_config_t;

/*!
 * @brief SPWM independent output configuration structure
 */
typedef struct
{
    spwm_counter_config_t         counterConfig;       /*!< Counter config */
    spwm_count_mode_t             countMode;           /*!< Counting mode */
    uint8_t                       channelNum;          /*!< Number of independent channels (0~7) */
    spwm_independent_ch_config_t *independentChConfig; /*!< Configuration for independent channels */
    bool                          initOutputEn;        /*!< Enable/Disable initial channel output */
    bool                          minTriggerEn;        /*!< Enable/Disable min trigger */
    bool                          maxTriggerEn;        /*!< Enable/Disable max trigger */
    spwm_trigger_ratio_t          triggerRatio;        /*!< External trigger ratio */
    bool                          intEn;               /*!< Enable/Disable NVIC */
#if (CONFIG_SPWM_UNIFIED_IRQ_FEATURE == 1U)
    spwm_callback_t callBack;                          /*!< Interrupt callback pointer */
#else
    spwm_callback_t channelCallBack;  /*!< Channel interrupt callback pointer */
    spwm_callback_t overflowCallBack; /*!< Overflow interrupt callback pointer */
#endif
} spwm_independent_output_config_t;

/*!
 * @brief SPWM combine channel configuration structure
 */
typedef struct
{
    spwm_channel_t                channel;           /*!< Combine channel number */
    uint16_t                      cv0;               /*!< Channel0 match value */
    uint16_t                      cv1;               /*!< Channel1 match value */
    spwm_output_mode_t            levelMode;         /*!< Output mode */
    bool                          complementEn;      /*!< Enable/Disable pair complementary */
    bool                          symmetricalEn;     /*!< Enable/Disable pair symmetrical */
    bool                          deadtimeEn;        /*!< Enable/Disable pair deadtime insert */
    uint16_t                      deadtimeVal;       /*!< Dual Channel deadtime value */
    spwm_deadtime_psc_t           deadtimePsc;       /*!< Dual Channel Dead time prescaler value */
    spwm_match_dir_t              ch0MatchDir;       /*!< Channel0 match dir */
    spwm_match_dir_t              ch1MatchDir;       /*!< Channel1 match dir */
    spwm_active_output_polarity_t ch0Polarity;       /*!< Channel0 active polarity */
    spwm_active_output_polarity_t ch1Polarity;       /*!< Channel1 active polarity */
    spwm_output_level_t           ch0InitLevel;      /*!< Channel init output level */
    spwm_output_level_t           ch1InitLevel;      /*!< Channel init output level */
    bool                          ch0MatchTriggerEn; /*!< Enable/Disable channel0 match trigger */
    bool                          ch1MatchTriggerEn; /*!< Enable/Disable channel1 match trigger */
    spwm_ch_event_ratio_t         ch0EventRatio;     /*!< Event prescaler */
    spwm_ch_event_ratio_t         ch1EventRatio;     /*!< Event prescaler */
    bool                          ch0IntEn;          /*!< Enable/Disable channel0 interrupt */
    bool                          ch1IntEn;          /*!< Enable/Disable channel1 interrupt */
} spwm_combine_ch_config_t;

/*!
 * @brief SPWM combine output configuration structure
 */
typedef struct
{
    spwm_counter_config_t     counterConfig;   /*!< Counter config */
    spwm_count_mode_t         countMode;       /*!< Counting mode */
    uint8_t                   channelNum;      /*!< Number of combine channels (0~3) */
    spwm_combine_ch_config_t *combineChConfig; /*!< Configuration for combine channels */
    bool                      initOutputEn;    /*!< Enable/Disable initial channel output */
    bool                      minTriggerEn;    /*!< Enable/Disable min trigger */
    bool                      maxTriggerEn;    /*!< Enable/Disable max trigger */
    spwm_trigger_ratio_t      triggerRatio;    /*!< External trigger ratio */
    bool                      intEn;           /*!< Enable/Disable NVIC */
#if (CONFIG_SPWM_UNIFIED_IRQ_FEATURE == 1U)
    spwm_callback_t callBack;                  /*!< Interrupt callback pointer */
#else
    spwm_callback_t channelCallBack;  /*!< Channel interrupt callback pointer */
    spwm_callback_t overflowCallBack; /*!< Overflow interrupt callback pointer */
#endif
} spwm_combine_output_config_t;

/*!
 * @brief SPWM output compare channel configuration structure
 */
typedef struct
{
    spwm_channel_t             channel;        /*!< Output Compare channel number */
    uint16_t                   comparedValue;  /*!< Output Compare channel value */
    spwm_output_compare_mode_t mode;           /*!< Output Compare mode */
    spwm_output_level_t        initLevel;      /*!< Channel init output level */
    bool                       matchTriggerEn; /*!< Enable/Disable channel match trigger */
    spwm_ch_event_ratio_t      eventRatio;     /*!< Event prescaler */
    bool                       chIntEn;        /*!< Enable/Disable channel interrupt */
} spwm_output_compare_ch_config_t;

/*!
 * @brief SPWM output compare configuration structure
 */
typedef struct
{
    spwm_counter_config_t counterConfig;        /*!< Counter config */
    uint8_t               channelNum;           /*!< Number of output compare channels (0~7) */
    spwm_output_compare_ch_config_t
                        *outputCompareChConfig; /*!< Configuration for output compare channels */
    bool                 initOutputEn;          /*!< Enable/Disable initial channel output */
    bool                 minTriggerEn;          /*!< Enable/Disable min trigger */
    bool                 maxTriggerEn;          /*!< Enable/Disable max trigger */
    spwm_trigger_ratio_t triggerRatio;          /*!< External trigger ratio */
    bool                 intEn;                 /*!< Enable/Disable NVIC */
#if (CONFIG_SPWM_UNIFIED_IRQ_FEATURE == 1U)
    spwm_callback_t callBack;                   /*!< Interrupt callback pointer */
#else
    spwm_callback_t channelCallBack;  /*!< Channel interrupt callback pointer */
    spwm_callback_t overflowCallBack; /*!< Overflow interrupt callback pointer */
#endif
} spwm_output_compare_config_t;

/*!
 * @brief SPWM single edge capture channel configuration structure
 */
typedef struct
{
    spwm_channel_t              channel;     /*!< Channel number */
    spwm_input_sensitive_edge_t captureType; /*!< In single mode, channel edge detect type */
    uint8_t                     filterValue; /*!< Filter value */
    bool                        chRst;       /*!< Enable/Disable channel reset */
    spwm_ch_event_ratio_t       eventRatio;  /*!< Event prescaler */
    bool                        chIntEn;     /*!< Enable/Disable channel interrupt */
} spwm_single_edge_capture_ch_config_t;

/*!
 * @brief SPWM single edge capture configuration structure
 */
typedef struct
{
    spwm_counter_config_t                 counterConfig; /*!< Counter config */
    uint8_t                               channelNum;    /*!< Number of output compare channels */
    spwm_single_edge_capture_ch_config_t *channelConfig; /*!< Input capture channels configuration */
    spwm_input_filter_psc_t               filterPsc;     /*!< Input filter psc */
    bool                                  intEn;         /*!< Enable/Disable NVIC */
#if (CONFIG_SPWM_UNIFIED_IRQ_FEATURE == 1U)
    spwm_callback_t callBack;                            /*!< Interrupt callback pointer */
#else
    spwm_callback_t channelCallBack;  /*!< Channel interrupt callback pointer */
    spwm_callback_t overflowCallBack; /*!< Overflow interrupt callback pointer */
#endif
} spwm_single_edge_capture_config_t;

/*!
 * @brief SPWM dual edge capture channel configuration structure
 */
typedef struct
{
    spwm_channel_t           channel;       /*!< Channel number */
    spwm_dual_edge_capture_t captureType;   /*!< Channel dual edge capture type */
    bool                     continousEn;   /*!< Enable/Disable dual edge capture continous mode */
    uint8_t                  filterValue;   /*!< Channel filter value */
    bool                     ch0Rst;        /*!< Enable/Disable channel0 cnt reset */
    bool                     ch1Rst;        /*!< Enable/Disable channel1 cnt reset */
    spwm_ch_event_ratio_t    ch0EventRatio; /*!< Channel0 Event prescaler */
    spwm_ch_event_ratio_t    ch1EventRatio; /*!< Channel1 Event prescaler */
    bool                     ch0IntEn;      /*!< Enable/Disable channel0 interrupt */
    bool                     ch1IntEn;      /*!< Enable/Disable channel1 interrupt */
} spwm_dual_edge_capture_ch_config_t;

/*!
 * @brief SPWM dual edge capture configuration structure
 */
typedef struct
{
    spwm_counter_config_t               counterConfig; /*!< Counter config */
    uint8_t                             channelNum;    /*!< Number of dual edge capture channels */
    spwm_dual_edge_capture_ch_config_t *channelConfig; /*!< Input capture channels configuration */
    spwm_input_filter_psc_t             filterPsc;     /*!< Input filter psc */
    bool                                hallEn;        /*!< Enable/Disable hall */
    bool                                intEn;         /*!< Enable/Disable NVIC */
#if (CONFIG_SPWM_UNIFIED_IRQ_FEATURE == 1U)
    spwm_callback_t callBack;                          /*!< Interrupt callback pointer */
#else
    spwm_callback_t channelCallBack;  /*!< Channel interrupt callback pointer */
    spwm_callback_t overflowCallBack; /*!< Overflow interrupt callback pointer */
#endif
} spwm_dual_edge_capture_config_t;

/*!
 * @brief SPWM Fault channel configuration structure
 */
typedef struct
{
    spwm_fault_input_t                 faultChannel;  /*!< Fault channel */
    bool                               faultInputEn;  /*!< Enable/Disable fault channe input */
    bool                               faultFilterEn; /*!< Enable/Disable fault input filter */
    spwm_fault_input_polarity_active_t faultPolarity; /*!< Fault channel input polarity active */
} spwm_fault_ch_config_t;

/*!
 * @brief SPWM fault configuration structure
 */
typedef struct
{
    bool                    faultEn;                             /*!< Fault */
    spwm_fault_ctrl_mode_t  mode;                                /*!< Fault control mode */
    uint8_t                 faultChannelNum;                     /*!< Fault channel num */
    spwm_fault_ch_config_t *channelConfig;                       /*!< Fault input channel configuration */
    spwm_input_filter_psc_t filterPsc;                           /*!< Fault input filter psc */
    uint8_t                 filterValue;                         /*!< Fault input filter value */
    bool                    faultCtrlOutputEn[SPWM_DUAL_CH_MAX]; /*!< Fault output mode control */
    bool                    HizEn;                               /*!< Enable/Disable fault Hiz output */
    bool                    faultIntEn;                          /*!< Enable/Disable fault interrupt */
#if (CONFIG_SPWM_INDEPENDENT_FAULT_INT == 1U)
    spwm_callback_t faultCallBack;                               /*!< Fault interrupt callback pointer */
#endif
} spwm_fault_config_t;

/*!
 * @brief SPWM sync configuration structure
 */
typedef struct
{
    spwm_sync_trigger_mode_t syncTriggerMode;      /*!< Synchronization trigger mode */
    bool                     hardwareSync0En;      /*!< Enable/Disable hardware sync trigger source 0 */
    bool                     hardwareSync1En;      /*!< Enable/Disable hardware sync trigger source 1 */
    bool                     autoClearHWTriggerEn; /*!< Available only for hardware trigger */
    bool                     outCtrlSyncEn;        /*!< Enable/Disable CHOSWCR sync */
    bool                     inverterSyncEn;       /*!< Enable/Disable INVCR sync */
    bool                     outmaskSyncEn;        /*!< Enable/Disable OMCR sync */
    bool                     counterSyncEn;        /*!< Enable/Disable MOD/CNTIN/CNV sync */
    bool                     maxLoadingPointEn;    /*!< Enable/Disable maximum loading point */
    bool                     minLoadingPointEn;    /*!< Enable/Disable minimum loading point */
    bool                     syncEn;               /*!< Enable/Disable Synchronization mode */
} spwm_sync_config_t;

/*******APIs*******************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @brief Configure SPWM channel independent output
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] config: Configuration of the independent output
 * @return None
 */
void SPWM_InitIndependentOutput(uint32_t instance, const spwm_independent_output_config_t *const config);

/*!
 * @brief Configure SPWM channel combine output
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] config: Configuration of the combine output
 * @return None
 */
void SPWM_InitCombineOutput(uint32_t instance, const spwm_combine_output_config_t *const config);

/*!
 * @brief Configure SPWM channel output compare
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] config: Configuration of the output compare
 * @return None
 */
void SPWM_InitOutputCompare(uint32_t instance, const spwm_output_compare_config_t *config);

/*!
 * @brief Configure SPWM channel single edge capture
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] config: Configuration of the single edge capture
 * @return None
 */
void SPWM_InitSingleEdgeCapture(uint32_t instance, const spwm_single_edge_capture_config_t *config);

/*!
 * @brief Configure SPWM channel dual edge capture
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] config: Configuration of the dual edge capture
 * @return None
 */
void SPWM_InitDualEdgeCapture(uint32_t instance, const spwm_dual_edge_capture_config_t *config);

/*!
 * @brief Enable/Disable the SPWM dual channel invert
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] channel: SPWM dual channel(SPWM_DUAL_CH_0~3)
 * @param[in] enable
 *            - true: Enable dual channel invert
 *            - false: Disable dual channel invert
 * @return None
 */
void SPWM_SetDualChannelInvert(uint32_t instance, spwm_dual_channel_t dualChannel, bool enable);

/*!
 * @brief Configure SPWM channel software output control
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] channel: SPWM channel(SPWM_CH0~7)
 * @param[in] enable
 *            - true: Enable software output control
 *            - false: Disable software output control
 * @param[in] level
 *            - 0: SPWM_LOW_LEVEL
 *            - 1: SPWM_HIGH_LEVEL
 * @return None
 */
void SPWM_SetChannelSoftwareControl(uint32_t instance, spwm_channel_t channel, bool enable,
                                    spwm_output_level_t level);

/*!
 * @brief Configure SPWM channel output mask
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] channel: SPWM channel(SPWM_CH0~7)
 * @param[in] enable
 *            - true: Enable output mask
 *            - false: Disable output mask
 * @return None
 */
void SPWM_SetChannelOutputMask(uint32_t instance, spwm_channel_t channel, bool enable);

/*!
 * @brief Configure SPWM fault function
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] config: Configuration of the fault function
 * @return None
 */
void SPWM_InitFaultControl(uint32_t instance, const spwm_fault_config_t *config);

/*!
 * @brief Set SPWM Modulo dither value
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] modDitherValue: modulo dither value
 * @return None
 */
void SPWM_SetModDither(uint32_t instance, uint8_t modDitherValue);

/*!
 * @brief Set the SPWM channel dither value
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] channel: SPWM channel(SPWM_CH0~7)
 * @param[in] chDitherValue: channel dither value
 * @return None
 */
void SPWM_SetChDither(uint32_t instance, spwm_channel_t channel, uint8_t chDitherValue);

/*!
 * @brief Set the SPWM counter initial value
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] cntInitValue: counter initial value
 * @return None
 */
void SPWM_SetCntInitVal(uint32_t instance, uint16_t cntInitValue);

/*!
 * @brief Set the SPWM channel value
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] channel: SPWM channel(SPWM_CH0~7)
 * @param[in] channelValue: channel value
 * @return None
 */
void SPWM_SetChannelValue(uint32_t instance, spwm_channel_t channel, uint16_t channelValue);

/*!
 * @brief Set the SPWM counter modulo value
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] modValue: counter modulo value
 * @return None
 */
void SPWM_SetMod(uint32_t instance, uint16_t modValue);

/*!
 * @brief Set the SPWM counter value
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] cntValue: counter value
 * @return None
 */
void SPWM_SetCounter(uint32_t instance, uint16_t cntValue);

/*!
 * @brief Get the SPWM current counter value
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @return Current counter value
 */
uint16_t SPWM_GetCounter(uint32_t instance);

/*!
 * @brief Get the SPWM channel value
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] channel: SPWM channel(SPWM_CH0~7)
 * @return Channel value
 */
uint16_t SPWM_GetChannelValue(uint32_t instance, spwm_channel_t channel);

/*!
 * @brief Get the SPWM all channel level
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @return All channel level
 */
uint8_t SPWM_GetChannelLevel(uint32_t instance);

/*!
 * @brief Get the SPWM fault flag
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @return All fault event flag
 */
uint8_t SPWM_GetFaultStatus(uint32_t instance);

/*!
 * @brief Enable/Disable the SPWM write protect
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] enable
 *            - true: Enable the write protect
 *            - false: Disable the write protect
 * @return None
 */
void SPWM_SetWriteProtect(uint32_t instance, bool enable);

/*!
 * @brief Configure SPWM register sync function
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] config: Configuration of the register sync function
 * @return None
 */
void SPWM_InitSyncContol(uint32_t instance, spwm_sync_config_t *config);

/*!
 * @brief Set software trigger to sync register
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @return None
 */
void SPWM_SetSoftwareTriggerSync(uint32_t instance);

/*!
 * @brief Enable/Disable the SPWM counter
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] enable
 *            - true: Enable the SPWM counter
 *            - false: Disable the SPWM counter
 * @return None
 */
void SPWM_SetCntEnable(uint32_t instance, bool cntEn);

/*!
 * @brief Enable/Disable SPWM global time base
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] enable
 *            - true: Enable global time base
 *            - false: Disable global time base
 * @return None
 */
void SPWM_SetGlobalTimeBaseEnable(uint32_t instance, bool enable);

/*!
 * @brief Enable/Disable SPWM global time base output
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @param[in] enable
 *            - true: Enable global time base output
 *            - false: Disable global time base output
 * @return None
 */
void SPWM_SetGlobalTimeBaseOutput(uint32_t instance, bool enable);

/*!
 * @brief Deinit SPWM
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @return None
 */
void SPWM_Deinit(uint32_t instance);

/*!
 * @brief SPWM commom IRQ handler Processing function
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @return None
 */
void SPWM_IRQHandlerProcess(uint32_t instance);

/*!
 * @brief SPWM channel IRQ handler Processing function
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @return None
 */
void SPWM_Channel_IRQHandlerProcess(uint32_t instance);

/*!
 * @brief SPWM fault IRQ handler Processing function
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @return None
 */
void SPWM_Fault_IRQHandlerProcess(uint32_t instance);

/*!
 * @brief SPWM overflow IRQ handler Processing function
 *
 * @param[in] instance: The SPWM peripheral instance number
 * @return None
 */
void SPWM_Overflow_IRQHandlerProcess(uint32_t instance);

#if defined(__cplusplus)
}
#endif

/*! @} */

#endif /* SPWM_DRV_H */

/*******EOF********************************************************************/
